package com.tywj.panda.customer.common.widget

import android.content.Context
import android.util.AttributeSet
import android.util.SparseIntArray
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.annotation.DimenRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.core.view.updateLayoutParams
import com.tywj.panda.customer.common.R
import com.tywj.lib.businessweak.widget.IStatusLayout
import com.tywj.lib.core.common.extension.invisible
import com.tywj.lib.core.common.extension.load
import com.tywj.lib.core.common.extension.onClick
import com.tywj.lib.core.common.extension.visible
import com.tywj.lib.core.common.util.ResourcesUtil
import com.tywj.lib.net.retrofit.request.BaseRequest
import kotlinx.android.synthetic.main.common_include_load_empty_or_error.view.*
import kotlinx.android.synthetic.main.common_include_load_loading.view.*

/**
 * <pre>
 *     author : June Yang
 *     time   : 2020/05/12
 *     desc   : 多状态布局，可以分别内容为空布局、加载出错布局、加载中布局、实际内容布局
 *     version: 1.9.0
 * </pre>
 */
class StatusLayout : FrameLayout, IStatusLayout {

    // 三种状态布局
    private var emptyLayout: View? = null
    private var errorLayout: View? = null
    private var loadingLayout: View? = null

    // 内容为空布局属性
    private var emptyLayoutIconTopSpaceDimenResId = R.dimen.dp_50
    private var emptyLayoutBackgroundResourceId = R.color.common_gray_F2
    private var emptyLayoutIconId = R.drawable.common_load_empty
    private var emptyLayoutTitleText = ResourcesUtil.getString(R.string.common_load_empty)
    private var emptyLayoutMessageText = ""
    private var isEmptyLayoutButtonVisible = true
    private var emptyLayoutButtonText = ResourcesUtil.getString(R.string.common_load_button_refresh)
    private var emptyLayoutButtonClickListener: ((View) -> Unit)? = null

    // 加载出错布局属性
    private var errorLayoutIconTopSpaceDimenResId = R.dimen.dp_50
    private var errorLayoutBackgroundResourceId = R.color.common_gray_F2
    private var errorLayoutIconId = R.drawable.common_load_error_server
    private var errorLayoutTitleText = ""
    private var errorLayoutMessageText = ""
    private var isErrorLayoutButtonVisible = true
    private var errorLayoutButtonText = ResourcesUtil.getString(R.string.common_load_button_refresh)
    private var errorLayoutButtonClickListener: ((View) -> Unit)? = null

    // 加载中布局属性
    private var loadingLayoutBackgroundResourceId = R.color.common_gray_F2

    private val layoutInflater: LayoutInflater by lazy { LayoutInflater.from(context) }

    // 当前显示的布局类型，默认显示实际内容布局
    private var currentLayoutType = IStatusLayout.TYPE_CONTENT

    // 布局变化监听
    private var layoutChangeListener: ((Int) -> Unit)? = null

    // 布局常量和实际的布局索引映射关系
    private val layoutIndexMap = SparseIntArray()

    constructor(context: Context) : this(context, null, 0)

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        layoutIndexMap.put(IStatusLayout.TYPE_CONTENT, 0)
    }

    override fun showEmptyLayout() {
        if (emptyLayout == null) {
            createEmptyLayout()
        }
        showLayoutByType(IStatusLayout.TYPE_EMPTY)
    }

    override fun showErrorLayout() {
        if (errorLayout == null) {
            createErrorLayout()
        }

        showLayoutByType(IStatusLayout.TYPE_ERROR)
    }

    override fun showErrorLayoutByCode(code: Int, message: String) {
        if (code < 0) {
            when (code) {
                BaseRequest.ERROR_NET, BaseRequest.ERROR_CONNECT -> {
                    errorLayoutIconId = R.drawable.common_load_error_net
                    errorLayoutTitleText = ResourcesUtil.getString(R.string.common_load_error_net)
                }
                else -> {
                    errorLayoutIconId = R.drawable.common_load_error_server
                    errorLayoutTitleText =
                        ResourcesUtil.getString(R.string.common_load_error_server)
                }
            }
        } else {
            errorLayoutIconId = R.drawable.common_load_error_server
            errorLayoutTitleText = message
        }
        errorLayoutButtonText = ResourcesUtil.getString(R.string.common_load_button_refresh)

        showErrorLayout()
    }

    override fun showLoadingLayout() {
        if (loadingLayout == null) {
            createLoadingLayout()
        }

        showLayoutByType(IStatusLayout.TYPE_LOADING)
    }

    override fun showContentLayout() {
        showLayoutByType(IStatusLayout.TYPE_CONTENT)
    }

    override fun setOnLayoutChangeListener(listener: (Int) -> Unit) {
        layoutChangeListener = listener
    }

    /**
     * 设置自定义内容为空布局，不使用默认布局
     * @param layout 自定义布局
     */
    fun setEmptyLayout(layout: View) {
        if (emptyLayout != null) {
            removeViewAt(IStatusLayout.TYPE_EMPTY)
        }

        emptyLayout = layout
        addEmptyLayout(layout)
        invisible(emptyLayout!!)
    }

    fun setEmptyLayoutBackgroundResource(@DrawableRes resId: Int) {
        emptyLayoutBackgroundResourceId = resId
        emptyLayout?.setBackgroundResource(resId)
    }

    fun setEmptyLayoutIconTopSpaceDimen(@DimenRes resId: Int) {
        emptyLayoutIconTopSpaceDimenResId = resId
        emptyLayout?.iconTopSpace?.updateLayoutParams<ViewGroup.LayoutParams> {
            height = ResourcesUtil.getDimensionPixelSize(resId)
        }
    }

    fun setEmptyLayoutIcon(@DrawableRes iconId: Int) {
        emptyLayoutIconId = iconId
        emptyLayout?.ivIcon?.load(iconId)
    }

    fun setEmptyLayoutTitle(@StringRes titleResId: Int) {
        setEmptyLayoutTitle(ResourcesUtil.getString(titleResId))
    }

    fun setEmptyLayoutTitle(title: String) {
        emptyLayoutTitleText = title
        emptyLayout?.tvTitle?.text = title
    }

    fun setEmptyLayoutMessage(@StringRes messageResId: Int) {
        setEmptyLayoutMessage(ResourcesUtil.getString(messageResId))
    }

    fun setEmptyLayoutMessage(message: String) {
        emptyLayoutMessageText = message
        emptyLayout?.tvMessage?.text = message
    }

    fun setEmptyLayoutButtonVisible(visible: Boolean) {
        isEmptyLayoutButtonVisible = visible
        emptyLayout?.btnRefresh?.let { toggleButtonVisibility(it, visible) }
    }

    fun setEmptyLayoutButtonText(@StringRes textId: Int) {
        setEmptyLayoutButtonText(ResourcesUtil.getString(textId))
    }

    fun setEmptyLayoutButtonText(text: String) {
        emptyLayoutButtonText = text
        emptyLayout?.btnRefresh?.text = text
    }

    fun setOnEmptyLayoutButtonClick(listener: (View) -> Unit) {
        emptyLayoutButtonClickListener = listener
        emptyLayout?.btnRefresh?.onClick { listener.invoke(it) }
    }

    /**
     * 设置自定义错误布局，不使用默认布局
     * @param layout 自定义布局
     */
    fun setErrorLayout(layout: View) {
        if (errorLayout != null) {
            removeViewAt(IStatusLayout.TYPE_ERROR)
        }

        errorLayout = layout
        addErrorLayout(layout)
        invisible(errorLayout!!)
    }

    fun setErrorLayoutBackgroundResource(@DrawableRes resId: Int) {
        errorLayoutBackgroundResourceId = resId
        errorLayout?.setBackgroundResource(resId)
    }

    fun setErrorLayoutIconTopSpaceDimen(@DimenRes resId: Int) {
        errorLayoutIconTopSpaceDimenResId = resId
        errorLayout?.iconTopSpace?.updateLayoutParams<ViewGroup.LayoutParams> {
            height = ResourcesUtil.getDimensionPixelSize(resId)
        }
    }

    fun setErrorLayoutIcon(@DrawableRes iconId: Int) {
        errorLayoutIconId = iconId
        errorLayout?.ivIcon?.load(iconId)
    }

    fun setErrorLayoutTitle(@StringRes titleResId: Int) {
        setErrorLayoutTitle(ResourcesUtil.getString(titleResId))
    }

    fun setErrorLayoutTitle(title: String) {
        errorLayoutTitleText = title
        errorLayout?.tvTitle?.text = title
    }

    fun setErrorLayoutMessage(@StringRes messageResId: Int) {
        setErrorLayoutMessage(ResourcesUtil.getString(messageResId))
    }

    fun setErrorLayoutMessage(message: String) {
        errorLayoutMessageText = message
        errorLayout?.tvMessage?.text = message
    }

    fun setErrorLayoutButtonVisible(visible: Boolean) {
        isErrorLayoutButtonVisible = visible
        errorLayout?.btnRefresh?.let { toggleButtonVisibility(it, visible) }
    }

    fun setErrorLayoutButtonText(@StringRes textId: Int) {
        setErrorLayoutButtonText(ResourcesUtil.getString(textId))
    }

    fun setErrorLayoutButtonText(text: String) {
        errorLayoutButtonText = text
        errorLayout?.btnRefresh?.text = text
    }

    fun setOnErrorLayoutButtonClick(listener: (View) -> Unit) {
        errorLayoutButtonClickListener = listener
        errorLayout?.btnRefresh?.onClick { listener.invoke(it) }
    }

    fun setLoadingLayoutBackgroundResource(@DrawableRes resId: Int) {
        loadingLayoutBackgroundResourceId = resId
        loadingLayout?.setBackgroundResource(resId)
    }

    private fun showLayoutByType(type: Int) {
        if (currentLayoutType == type) {
            return
        }

        if (type == IStatusLayout.TYPE_LOADING) {
            // 要显示加载中布局，显示加载中动画
            loadingLayout?.loadingView?.startAnimation()
        }
        if (currentLayoutType == IStatusLayout.TYPE_LOADING) {
            // 从加载中布局切换到其他布局，取消加载中动画
            loadingLayout?.loadingView?.cancelAnimation()
        }

        val count = childCount
        val realIndex = layoutIndexMap.get(type)
        for (i in 0 until count) {
            val view = getChildAt(i)
            if (i == realIndex) {
                visible(view)
            } else {
                invisible(view)
            }
        }

        currentLayoutType = type
        layoutChangeListener?.invoke(currentLayoutType)
    }

    private fun createEmptyLayout() {
        val layout = layoutInflater.inflate(
            R.layout.common_include_load_empty_or_error, this, false
        )

        layout.setBackgroundResource(emptyLayoutBackgroundResourceId)
        layout.iconTopSpace.updateLayoutParams<ViewGroup.LayoutParams> {
            height = ResourcesUtil.getDimensionPixelSize(emptyLayoutIconTopSpaceDimenResId)
        }
        layout.ivIcon.load(emptyLayoutIconId)
        layout.tvTitle.text = emptyLayoutTitleText
        layout.tvMessage.text = emptyLayoutMessageText
        toggleButtonVisibility(layout.btnRefresh, isEmptyLayoutButtonVisible)
        layout.btnRefresh.text = emptyLayoutButtonText
        layout.btnRefresh.onClick { emptyLayoutButtonClickListener?.invoke(it) }

        addEmptyLayout(layout)
    }

    private fun addEmptyLayout(layout: View) {
        emptyLayout = layout
        val count = childCount
        addView(layout, count)
        layoutIndexMap.put(IStatusLayout.TYPE_EMPTY, count)
    }

    private fun createErrorLayout() {
        val layout = layoutInflater.inflate(
            R.layout.common_include_load_empty_or_error, this, false
        )

        layout.setBackgroundResource(errorLayoutBackgroundResourceId)
        layout.iconTopSpace.updateLayoutParams<ViewGroup.LayoutParams> {
            height = ResourcesUtil.getDimensionPixelSize(errorLayoutIconTopSpaceDimenResId)
        }
        layout.ivIcon.load(errorLayoutIconId)
        layout.tvTitle.text = errorLayoutTitleText
        layout.tvMessage.text = errorLayoutMessageText
        toggleButtonVisibility(layout.btnRefresh, isErrorLayoutButtonVisible)
        layout.btnRefresh.text = errorLayoutButtonText
        layout.btnRefresh.onClick { errorLayoutButtonClickListener?.invoke(it) }

        addErrorLayout(layout)
    }

    private fun addErrorLayout(layout: View) {
        errorLayout = layout
        val count = childCount
        addView(layout, count)
        layoutIndexMap.put(IStatusLayout.TYPE_ERROR, count)
    }

    private fun createLoadingLayout() {
        val layout = layoutInflater.inflate(R.layout.common_include_load_loading, this, false)

        layout.setBackgroundResource(loadingLayoutBackgroundResourceId)

        loadingLayout = layout
        val count = childCount
        addView(layout, count)
        layoutIndexMap.put(IStatusLayout.TYPE_LOADING, count)
    }

    private fun toggleButtonVisibility(view: View, visible: Boolean) {
        if (visible) {
            view.visibility = View.VISIBLE
        } else {
            view.visibility = View.INVISIBLE
        }
    }
}
